package il.ac.biu.cs.grossmm.api.keys;

public interface KeyPattern {

	/**
	 * A key pattern which matches any key
	 */
	public static KeyPattern ANY_KEY = new BaseKeyPattern(true, Object.class, false);

	/**
	 * A key pattern which matches a key with any value and no subkeys
	 */
	public static KeyPattern ANY_SIMPLE_KEY = new BaseKeyPattern(false, Object.class, false);
	
	/**
	 * A key pattern which matches a key with a null value and no subkeys
	 */
	public static KeyPattern ONLY_NULL_KEY = new BaseKeyPattern(true, Void.class, false);

	/**
	 * A key pattern such that no key matches against it
	 */
	public static KeyPattern NONE = new None();

	/**
	 * Returns an exact value to match. The return value of this method have no
	 * any meaning if <tt>getValueClass</tt> does mot return null.
	 * 
	 * @return exact value to match, valid only if <tt>getValueClass</tt> does
	 *         mot return null
	 */
	Object value();

	/**
	 * Returns a value class or null. If returns a non-null, the
	 * <tt>getValue</tt> return value must be ignored.
	 * 
	 * @return a value class or null
	 */
	Class valueClass();

	/**
	 * Returns true if this object is a mask, false otherwise A mask pattern
	 * allows keys to contain attributes specified in the pattern (if they match
	 * the restrictions) and any other attributes. A non-mask pattern does not
	 * allow keys to contain attributes not specified in this pattern.
	 * 
	 * @return true if this object is a mask, false otherwise
	 */
	boolean isMask();

	/**
	 * Returns number of pattern entries in this pattern
	 * 
	 * @return number of pattern entries in this pattern
	 */
	int size();

	/**
	 * Returns i-th pattern entry in this pattern
	 * 
	 * @param i
	 *            the ordinal number of pattern entry to return
	 * @return i-th pattern entry in this pattern
	 */
	PatternEntry entry(int i);

	/**
	 * Returns pattern entry for given attribut
	 * 
	 * @param a
	 *            attribute to specify pattern entry to be returned
	 * @returnpattern entry for given attribute
	 */
	PatternEntry entry(Attribute a);

	/**
	 * Returns subpattern for given attribute. The semantics of this method is
	 * equivalent to semantics of the following expression:
	 * 
	 * <pre>
	 * enyry(a) == null ? null : entry(a).getPattern()
	 * </pre>
	 * 
	 * @param a
	 *            attribute to specify pattern entry to be returned
	 * @return subpattern for given attribute
	 */
	KeyPattern subpattern(Attribute a);

	/**
	 * A class of NONE, no other pattern belongs to this class (singleton).
	 */
	class None extends BaseKeyPattern {
		private static final Object UNMATCHABLE = new Object();

		private None()
		{
			super(false, UNMATCHABLE, true);
		}
		
		@Override
		public String toString()
		{
			return "NONE-pattern";
		}
	}
}
